package com.youlai.wh.service;

import cn.hutool.core.lang.Assert;
import com.youlai.utils.IdWorker;
import com.youlai.wh.entity.WhLocationEntity;
import com.youlai.common.model.Option;
import com.youlai.utils.DateUtils;
import com.youlai.system.util.SecurityUtils;
import com.youlai.core.security.model.SysUserDetails;
import com.youlai.wh.query.PageQuery;
import com.youlai.wh.repository.WhLocationRepository;
import com.youlai.system.service.SysDictService;
import jakarta.annotation.Resource;
import jakarta.persistence.criteria.CriteriaBuilder;
import jakarta.persistence.criteria.CriteriaQuery;
import jakarta.persistence.criteria.Predicate;
import jakarta.persistence.criteria.Root;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class WhLocationService {
    @Autowired
    private WhLocationRepository repository;

    @Resource
    SysDictService sysDictService;

    /**
     * 分页查询列表
     *
     * @param queryParams
     * @return
     */
    public Page<WhLocationEntity> getPage(PageQuery queryParams) {
        // 查询参数
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        String keywords = queryParams.getKeywords();
        DateUtils.toDatabaseFormat(queryParams, "startUpdateTime", "endUpdateTime");

        Sort sort =  Sort.by(Sort.Direction.DESC,"updateTime");   // .and(Sort.by("createTime").descending());
        Pageable pageable = PageRequest.of(pageNum-1, pageSize, sort);
        //动态查询
        Specification<WhLocationEntity> spec  = (Root<WhLocationEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (StringUtils.isNotBlank(queryParams.getName())) {
                predicates.add(cb.like(root.get("name"), "%" + queryParams.getName() + "%"));
            }
            if (queryParams.getCode() != null) {
                predicates.add(cb.equal(root.get("code"), queryParams.getCode()));
            }

            if (queryParams.getStartUpdateTime() != null && queryParams.getEndUpdateTime() != null) {
                Date StartUpdateTimeDate = DateUtils.strToDateLong(queryParams.getStartUpdateTime());
                Date endUpdateTimeDate = DateUtils.strToDateLong(queryParams.getEndUpdateTime());
                predicates.add(cb.between(root.get("updateTime"), StartUpdateTimeDate, endUpdateTimeDate));
            }
            //查询发送成功并且未删除的
            predicates.add(cb.equal(root.get("deleted"), 0));
            Predicate predicate = cb.and(predicates.toArray(new  Predicate[predicates.size()]));

            if (StringUtils.isNotBlank(queryParams.getKeywords())) {
                Predicate predicateOr =  cb.or(
                        cb.equal(root.get("storeCode"), queryParams.getKeywords()),
                        cb.equal(root.get("location"), queryParams.getKeywords())
                );
                predicate = cb.and(predicate, predicateOr);
            }
            return predicate;
        };
        Page<WhLocationEntity> page = repository.findAll(spec, pageable);
        return page;
    }

    public void save(WhLocationEntity entity){
        // 校验员工编号是否存在
        String storeCode = entity.getStoreCode();
        String location = entity.getLocation();
        Specification<WhLocationEntity> spec  = (Root<WhLocationEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) -> {
            Predicate predicate = cb.and(cb.equal(root.get("storeCode"), storeCode));
            predicate = cb.and(cb.equal(root.get("location"), location),predicate);
            return predicate;
        };
        long count = repository.count(spec);
        Assert.isTrue(count == 0, "该仓库+库位已存在");

        SysUserDetails user = SecurityUtils.getUser();
        entity.setWhLocationId(IdWorker.generateId());
        entity.setCreateBy(user.getUserId());
        entity.setCreateName(user.getUsername());
        entity.setCreateTime(new Date());
        entity.setUpdateBy(user.getUserId());
        entity.setUpdateName(user.getUsername());
        entity.setUpdateTime(new Date());
        repository.save(entity);
    }

    public void update(WhLocationEntity entity){
        // 校验员工编号是否存在
        String storeCode = entity.getStoreCode();
        String location = entity.getLocation();
        Specification<WhLocationEntity> spec  = (Root<WhLocationEntity> root, CriteriaQuery<?> cq, CriteriaBuilder cb) -> {
            Predicate predicate = cb.and(cb.equal(root.get("storeCode"), storeCode));
            predicate = cb.and(cb.equal(root.get("location"), location),predicate);
            predicate = cb.and(cb.notEqual(root.get("whLocationId"), entity.getWhLocationId()),predicate);
            return predicate;
        };
        long count = repository.count(spec);
        Assert.isTrue(count == 0, "该仓库+库位已存在");

        SysUserDetails user = SecurityUtils.getUser();
        entity.setUpdateBy(user.getUserId());
        entity.setUpdateName(user.getUsername());
        entity.setUpdateTime(new Date());
        repository.save(entity);

        //@todo 当用户在这里更改库位代码时，系统会自动更新货号清单中的所有库位代码。
    }

    public WhLocationEntity findById(Long id){
        Optional<WhLocationEntity> optional  = repository.findById(id);
        if(optional.isPresent()) {
            return optional.get();
        }
        return null;
    }

    public Boolean deleteAllById(String idStrs){
        SysUserDetails user = SecurityUtils.getUser();
        // 逻辑删除
        List<Long> ids = Arrays.asList(idStrs.split(",")).stream()
                .map(idStr -> Long.parseLong(idStr)).collect(Collectors.toList());
        for(Long id:ids) {
            Optional<WhLocationEntity> optional  = repository.findById(id);
            if(optional.isPresent()) {
                WhLocationEntity entity = optional.get();
                entity.setDeleted(1);

                entity.setUpdateBy(user.getUserId());
                entity.setUpdateName(user.getUsername());
                entity.setUpdateTime(new Date());
                repository.save(entity);
            }
        }
        return true;
    }


    public List<Option> listStoreBinOptions() {
        Specification<WhLocationEntity> spec  = (Root<WhLocationEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) -> {
            Predicate predicate = cb.and(cb.equal(root.get("status"), 1));
            predicate = cb.and(cb.equal(root.get("deleted"), 0), predicate);
            return predicate;
        };
        List<WhLocationEntity> list = repository.findAll(spec);
        List<Option> lastList = new ArrayList<>();
        for(WhLocationEntity o:list) {
            Option option = new Option();
            option.setLabel(o.getDescription());
            option.setValue(o.getStoreCode()+","+o.getLocation());
            lastList.add(option);
        }
        return lastList;
    }
}


